﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MongoDB.Driver;
using Sustainalytics.BusinessResearchProductStates.Entities.ResearchState;
using Sustainalytics.ESG.Entities;
using Sustainalytics.ClientDW.Entities;

namespace Sustainalytics.CRT.Synchronization
{
    public class FocusedRatingAggregatesProcessor
    {
        private readonly Dictionary<string, RPCompanyESGComputationResult> peerGroupComputationResults;

        public FocusedRatingAggregatesProcessor(IMongoCollection<RPCompanyESGComputationResult> esgComputationResultCollection, IMongoCollection<CorporateData> corporateDataCollection)
        {
            peerGroupComputationResults = new Dictionary<string, RPCompanyESGComputationResult>();
            Init(esgComputationResultCollection, corporateDataCollection).ConfigureAwait(false).GetAwaiter().GetResult();
        }

        public void AppendGroupAggregates(RPCompanyESGComputationResult result, string peerGroupShortName)
        {
            if (peerGroupComputationResults.ContainsKey(peerGroupShortName) && peerGroupComputationResults[peerGroupShortName] != null)
            {
                var peerOverallPerformance = peerGroupComputationResults[peerGroupShortName].OverallPerformance;
                result.OverallPerformance.Avg = peerOverallPerformance.Avg;
                result.OverallPerformance.Min = peerOverallPerformance.Min;
                result.OverallPerformance.Max = peerOverallPerformance.Max;
            }
        }

        public void AppendTop5ToResult(RPCompanyESGComputationResult result, string peerGroupShortName, string companyName)
        {
            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            if (string.IsNullOrEmpty(peerGroupShortName))
            {
                throw new ArgumentNullException(nameof(peerGroupShortName));
            }

            if (peerGroupComputationResults.ContainsKey(peerGroupShortName) && peerGroupComputationResults[peerGroupShortName] != null)
            {
                if (result.RelativePosition == null)
                {
                    result.RelativePosition = new RPRelativePosition();
                }

                result.RelativePosition.TopList = new FocusedRatingsIndustryListManager(peerGroupComputationResults[peerGroupShortName].RelativePosition.TopList).GetIndustryPeersForCompany(result, companyName);
            }
        }

        private async Task Init(IMongoCollection<RPCompanyESGComputationResult> esgComputationResultCollection, IMongoCollection<CorporateData> corporateDataCollection)
        {
            await corporateDataCollection
            .Aggregate()
            .Match(x => x.ComprehensiveEsgResearchState.ResearchState == ResearchState.ResearchAvailable)
            .Group(x => x.PeerGroup, x => new { x.First().PeerGroup, x.First().Id })
            .ForEachAsync(async g =>
            {
                var top = await esgComputationResultCollection.Find(x => x.Id == g.Id).FirstOrDefaultAsync().ConfigureAwait(false);
                peerGroupComputationResults.Add(g.PeerGroup, top);
            }).ConfigureAwait(false);
        }
    }
}